package com.june.filewatch;

import java.nio.file.FileSystems;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.nio.file.WatchEvent.Kind;
import java.nio.file.WatchKey;
import java.nio.file.WatchService;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;

public class FileWatch {

	private static Map<WatchKey,FileVisitor> watchKeyThread = new ConcurrentHashMap<>();
	/**
	 * 对指定文件夹进行监控
	 * @author June
	 * @param filePath 文件夹路径
	 * @param watchSubtree 是否监控文件夹中的子文件夹
	 * @param dirListener 是否响应文件夹上的事件
	 * @param fileListener 响应处理函数所在接口的实现
	 * @param mask 监控的内容
	 * @return 监控的标志，取消监控时使用
	 */
	@SafeVarargs
	public static WatchKey addWatch(String filePath,boolean watchSubtree,boolean dirListener,FileListener fileListener,Kind<Path>... mask) throws Exception{
		WatchService watcher = FileSystems.getDefault().newWatchService(); 
		Path path = Paths.get(filePath);
		if(!path.toFile().isDirectory()){
			throw new Exception("只能对文件夹进行监控");
		}
		WatchKey watchKey = path.register(watcher, mask);
		Map<WatchKey,Path> watchKeyPath = new ConcurrentHashMap<>();
		watchKeyPath.put(watchKey, path);
		FileVisitor visitor = new FileVisitor(watchSubtree,dirListener,watchKeyPath,watcher, mask,fileListener);
		if(watchSubtree){
			Files.walkFileTree(path, visitor);
		}
		Thread thread = new Thread(visitor);
		watchKeyThread.put(watchKey,visitor);
		thread.start();
		return watchKey;
	}
	
	/**
	 * 取消文件夹的监控
	 * @author June
	 * @param watchKey 监控的标志，添加监控时得到
	 */
	public static void removeWatch(WatchKey watchKey){
		FileVisitor visitor = watchKeyThread.get(watchKey);
		watchKey.cancel();
		visitor.setStop();
	}
}
